package il.ac.bgu.cs.heuristics.core;

import il.ac.bgu.cs.heuristics.graph.State;
import il.ac.bgu.cs.heuristics.graph.types.IActionGraph;
import il.ac.bgu.cs.heuristics.graph.types.IPath;
import il.ac.bgu.cs.heuristics.graph.types.IState;
import il.ac.bgu.cs.heuristics.graph.types.ISubstitution;

import java.util.LinkedList;
import java.util.Queue;
import java.util.Set;

public class HeuristicsEngineIterativeWithMemory extends heuristicsEngine
		implements IHeuristicsEngine {

	IState	init	= null;

	public HeuristicsEngineIterativeWithMemory(IActionGraph aGraph) {
		super(aGraph);
		// TODO Auto-generated constructor stub
	}

	@Override
	public int getHValue(IState init, IState goal) {
		this.init = init;
		aGraph.setInitState(init);
		int maxHValue = Integer.MIN_VALUE;
		int hValue = 0;
		return extractLightHeuristicIterativeWithMemory(goal);
	}

	private int extractLightHeuristicIterativeWithMemory(IState goal) {
		Queue<ExtendenSearchNode> searchQueue = new LinkedList<ExtendenSearchNode>();
		Queue<ExtendenSearchNode> alreadyVisitedQueue = new LinkedList<ExtendenSearchNode>();
		searchQueue.add(new ExtendenSearchNode(null, null, goal));
		ExtendenSearchNode currentNode = null;
		while (!searchQueue.isEmpty()) {
			currentNode = searchQueue.poll();
			if (currentNode.reached)
				continue;
			// TODO - fix this
			// if (init.contains(currentNode.getSubgoal()))
			// return currentNode.getCurrentDistanceToGoal();

			Set<IState> subgoals = aGraph
					.getNonContradictingEffects(currentNode.subgoal);
			subgoals = filterGoals(init, currentNode.subgoal, subgoals,
					new NotUsefulGoalsStateFilter());

			for (IState subgoal : subgoals) {
				IPath subgoalPath = aGraph.getShortestPath(init, subgoal);
				Set<ISubstitution> ConstraintsList = subgoalPath
						.getConstraints();
				ConstraintsList = init
						.getNotContainedSubstitution(ConstraintsList);
				if (ConstraintsList.isEmpty()) {
					int returnHvalue = currentNode.sonIsComplete(subgoal,
							subgoalPath.weight());
					if (returnHvalue > 0)
						return returnHvalue;

				} else {
					currentNode.actionGoalsList.add(new ExtendenSearchNode(
							currentNode, subgoal, State
									.createState(ConstraintsList)));
				}
			}
			// adding all the child searchNodes.
			searchQueue.addAll(currentNode.actionGoalsList);

		}
		throw new IllegalArgumentException("this mean we dont have solution");
	}

}
